//
// Created by 95233 on 2024/4/30.
//

#include "Chess.h"
#include <cmath>
#include <iostream>
#include <graphics.h>
#include <conio.h>

using namespace std;

void Chess::init() {
    //创建游戏窗口
    initgraph(950, 950);
    //显示棋盘图片，可以相对路径
    loadimage(0, "../res/broad.png");
    // 加载棋子图片,同时缩放图片 需要绝对路径
    loadimage(&chessBlackImag, "C:\\Users\\95233\\Desktop\\c++Learn\\AiPlay\\res\\black.png", 45, 45, true);
    cout << "黑棋：" << &chessBlackImag << endl;
    // 加载白棋图片
    loadimage(&chessWhiteImag, "C:\\Users\\95233\\Desktop\\c++Learn\\AiPlay\\res\\white.png", 45, 45, true);
    cout << "白棋：" << &chessWhiteImag << endl;

    //清理棋盘
    for (int i = 0; i < gradeSize; ++i) {
        for (int j = 0; j < gradeSize; ++j) {
            chessMap[i][j] = 0;
        }
    }
    player = true;
}


// 判断当前鼠标点击的位置
bool Chess::clickBoard(int x, int y, ChessPos *pos) {
    int row = (y - marginY) / chessSize;// 行
    int col = (x - marginX) / chessSize;// 列
    int recentCellXPosition = marginX + col * chessSize;
    int recentCellYPosition = marginY + row * chessSize;
    int offset = chessSize * 0.4;//偏移量，判断点击位置靠近四个角的哪个角，则落子在哪个角
    int xLen;//用于计算长度
    int yLen;
    int len;
    bool res = false;
    cout << "x=" << x << ",y=" << y << ",marginX=" << marginX << ",marginY=" << marginY <<
         ",chessSize=" << chessSize << ",row=" << row << ",col=" << col <<
         ",recentCellXPosition=" << recentCellXPosition << ",recentCellYPosition=" << recentCellYPosition <<
         ",offset=" << offset << endl;
    do {
        // 左上角判断
        xLen = x - recentCellXPosition;
        yLen = y - recentCellYPosition;
        cout << "xLen=" << xLen << ",yLen=" << yLen << endl;
        len = sqrt(xLen * xLen
                   + yLen * yLen);
        cout << "左上角，len=" << len << ",offset=" << offset << endl;

        if (len < offset) {

            pos->row = row;
            pos->col = col;
            // 判断当前位置是否已经有棋子
            if (chessMap[pos->row][pos->col] == 0) {
                cout << "左上角判断，当前位置无落子" << endl;

                res = true;
            }
            break;
        }
        cout << "左上角判断失败！" << endl;

        // 右上角的判断 c - ( x - r)
        xLen = chessSize - (x - recentCellXPosition);
        yLen = y - recentCellYPosition;
        cout << "xLen=" << xLen << ",yLen=" << yLen << endl;
        len = sqrt(xLen * xLen
                   + yLen * yLen);
        cout << "右上角，len=" << len << ",offset=" << offset << endl;

        if (len < offset) {

            pos->row = row;
            pos->col = col + 1;
            // 判断当前位置是否已经有棋子
            if (chessMap[pos->row][pos->col] == 0) {
                cout << "右上角判断，当前位置无落子" << endl;
                res = true;
            }
            break;
        }
        cout << "右上角判断失败！" << endl;

        // 左下角的判断
        xLen = x - recentCellXPosition;
        yLen = chessSize - (y - recentCellYPosition);
        cout << "xLen=" << xLen << ",yLen=" << yLen << endl;
        len = sqrt(xLen * xLen
                   + yLen * yLen);
        cout << "左下角，len=" << len << ",offset=" << offset << endl;
        if (len < offset) {
            pos->row = row + 1;
            pos->col = col;
            // 判断当前位置是否已经有棋子
            if (chessMap[pos->row][pos->col] == 0) {
                cout << "左下角判断，当前位置无落子" << endl;
                res = true;
            }
            break;
        }
        cout << "左下角判断失败！" << endl;

        // 右下角的判断
        xLen = chessSize - (x - recentCellXPosition);
        yLen = chessSize - (y - recentCellYPosition);
        cout << "xLen=" << xLen << ",yLen=" << yLen << endl;
        len = sqrt(xLen * xLen
                   + yLen * yLen);
        cout << "右下角，len=" << len << ",offset=" << offset << endl;

        if (len < offset) {
            pos->row = row + 1;
            pos->col = col + 1;
            // 判断当前位置是否已经有棋子
            if (chessMap[pos->row][pos->col] == 0) {
                cout << "右下角判断，当前位置无落子" << endl;
                res = true;
            }
            break;
        }
        cout << "右下角判断失败！" << endl;

    } while (false);
    cout << "ret is " + to_string(res) << endl;
    return res;
}


void Chess::chessDown(ChessPos *pos, chess_kind_t kind) {
    int x = marginX + chessSize * pos->col - 0.5 * chessSize;
    int y = marginY + chessSize * pos->row - 0.5 * chessSize;
    cout << "画棋子的位置：x=" << x << ",y=" << y << endl;
    if (kind == CHESS_WHITE) {
        cout << "显示白棋！" << endl;
        putImagePNG(x, y, &chessWhiteImag);

    } else {
        cout << "显示黑棋！" << endl;
        putImagePNG(x, y, &chessBlackImag);
    }
    updateGameMap(pos);
}

int Chess::getGradeSize() {
    return gradeSize;
}

int Chess::getChessData(ChessPos *pos) {
    return this->chessMap[pos->row][pos->col];
}

int Chess::getChessData(int row, int col) {
    return this->chessMap[row][col];
}

bool Chess::checkOver() {
    cout << "checkOver:" << to_string(checkGameState()) << endl;
    if (checkGameState()) {
        Sleep(1000);
        if (player) {
            loadimage(0, "../res/fail.gif");
        } else {
            loadimage(0, "../res/win.gif");
        }
        _getch();// 暂停
        return true;
    }
    return false;
}

Chess::Chess(int gradeSize, int marginX, int marginY, float chessSize) {
    this->gradeSize = gradeSize;
    this->marginX = marginX;
    this->marginY = marginY;
    this->chessSize = chessSize;
    player = CHESS_BLACK;
    for (int i = 0; i < gradeSize; ++i) {
        vector<int> row;
        for (int j = 0; j < gradeSize; ++j) {
            row.push_back(0);
        }
        chessMap.push_back(row);
    }
}

void Chess::updateGameMap(ChessPos *pos) {
    cout << "更新GameMap" << endl;
    lastPos = *pos;
    chessMap[pos->row][pos->col] = player ? CHESS_BLACK : CHESS_WHITE;
    player = !player;//落子人 黑白交换
}

void Chess::putImagePNG(int x, int y, IMAGE *picture) {//x为载入图片的X坐标，y为Y坐标
    cout << "putImagePNG" << endl;
    // 变量初始化
    DWORD *dst = GetImageBuffer();    // GetImageBuffer()函数，用于获取绘图设备的显存指针，EASYX自带
    DWORD *draw = GetImageBuffer();
    DWORD *src = GetImageBuffer(picture); //获取picture的显存指针
    int picture_width = picture->getwidth(); //获取picture的宽度，EASYX自带
    int picture_height = picture->getheight(); //获取picture的高度，EASYX自带
    int graphWidth = getwidth();       //获取绘图区的宽度，EASYX自带
    int graphHeight = getheight();     //获取绘图区的高度，EASYX自带
    int dstX = 0;    //在显存里像素的角标

    // 实现透明贴图 公式： Cp=αp*FP+(1-αp)*BP ， 贝叶斯定理来进行点颜色的概率计算
    for (int iy = 0; iy < picture_height; iy++) {
        for (int ix = 0; ix < picture_width; ix++) {
            int srcX = ix + iy * picture_width; //在显存里像素的角标
            int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度
            int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R
            int sg = ((src[srcX] & 0xff00) >> 8);   //G
            int sb = src[srcX] & 0xff;              //B
            if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight) {
                dstX = (ix + x) + (iy + y) * graphWidth; //在显存里像素的角标
                int dr = ((dst[dstX] & 0xff0000) >> 16);
                int dg = ((dst[dstX] & 0xff00) >> 8);
                int db = dst[dstX] & 0xff;
                draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255)
                        << 16)  //公式： Cp=αp*FP+(1-αp)*BP  ； αp=sa/255 , FP=sr , BP=dr
                             | ((sg * sa / 255 + dg * (255 - sa) / 255) << 8)         //αp=sa/255 , FP=sg , BP=dg
                             | (sb * sa / 255 + db * (255 - sa) / 255);              //αp=sa/255 , FP=sb , BP=db
            }
        }
    }
}

bool Chess::checkGameState() {
    // 横竖斜四种大情况，每种情况都根据当前落子往后遍历5个棋子，有一种符合就算赢
    // 水平方向
    int row = lastPos.row;
    int col = lastPos.col;

    for (int i = 0; i < 5; i++) {
        // 往左5个，往右匹配4个子，20种情况
        if (col - i >= 0 &&
            col - i + 4 < gradeSize &&
            chessMap[row][col - i] == chessMap[row][col - i + 1] &&
            chessMap[row][col - i] == chessMap[row][col - i + 2] &&
            chessMap[row][col - i] == chessMap[row][col - i + 3] &&
            chessMap[row][col - i] == chessMap[row][col - i + 4])
            return true;
    }

    // 竖直方向(上下延伸4个)
    for (int i = 0; i < 5; i++) {
        if (row - i >= 0 &&
            row - i + 4 < gradeSize &&
            chessMap[row - i][col] == chessMap[row - i + 1][col] &&
            chessMap[row - i][col] == chessMap[row - i + 2][col] &&
            chessMap[row - i][col] == chessMap[row - i + 3][col] &&
            chessMap[row - i][col] == chessMap[row - i + 4][col])
            return true;
    }

    // “/"方向
    for (int i = 0; i < 5; i++) {
        if (row + i < gradeSize &&
            row + i - 4 >= 0 &&
            col - i >= 0 &&
            col - i + 4 < gradeSize &&
            // 第[row+i]行，第[col-i]的棋子，与右上方连续4个棋子都相同
            chessMap[row + i][col - i] == chessMap[row + i - 1][col - i + 1] &&
            chessMap[row + i][col - i] == chessMap[row + i - 2][col - i + 2] &&
            chessMap[row + i][col - i] == chessMap[row + i - 3][col - i + 3] &&
            chessMap[row + i][col - i] == chessMap[row + i - 4][col - i + 4])
            return true;
    }

    // “\“ 方向
    for (int i = 0; i < 5; i++) {
        // 第[row+i]行，第[col-i]的棋子，与右下方连续4个棋子都相同
        if (row - i >= 0 &&
            row - i + 4 < gradeSize &&
            col - i >= 0 &&
            col - i + 4 < gradeSize &&
            chessMap[row - i][col - i] == chessMap[row - i + 1][col - i + 1] &&
            chessMap[row - i][col - i] == chessMap[row - i + 2][col - i + 2] &&
            chessMap[row - i][col - i] == chessMap[row - i + 3][col - i + 3] &&
            chessMap[row - i][col - i] == chessMap[row - i + 4][col - i + 4])
            return true;
    }

    return false;
}

